import Cluster from 'ol/source/Cluster';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import { Fill, Stroke, Style, Circle, Text, Icon } from 'ol/style';
import { Feature } from 'ol';
import { Point } from 'ol/geom';
import LineString from 'ol/geom/LineString';
import Polygon from 'ol/geom/Polygon';
function Vector(map) {
    this.map = map;
    this.clusterLayer = null;
    this.infoKey = null;
}

/**
 * description 添加碰撞点
 * @param points 点数值，每个对象包含点坐标、相关信息
 */
Vector.prototype.addCollisionPoints = function (vectorObj = {}) {
    let features = vectorObj.features;
    let distance = vectorObj.distance;
    let styleObj = vectorObj.style || {};

    //   if (this.collisionLayer) {
    //     this.collisionLayer.getSource().clear();
    //   }

    let vectorSource = new VectorSource();
    features.forEach((feature) => {
        vectorSource.addFeature(feature);
    });

    let collisionPondSource = new Cluster({
        distance: distance || 100,
        source: vectorSource
    });

    let self = this;
    let collisionLayer = new VectorLayer({
        id: 'layerPondIcon',
        title: 'layerPondIcon',
        source: collisionPondSource,
        zIndex: 30,
        style: function (feature) {
            return self.collisionStyle(feature, styleObj);
        }
    });

    this.map.addLayer(collisionLayer);
    return collisionLayer;
};

/**
 * @description: 设置单个碰撞点样式
 * @param {*} vectorObj
 * pointArr 坐标,必传 格式[x,y]
 * layer 图层对象,必传
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}
 */
Vector.prototype.setCollisionPoint = function (vectorObj) {
    const pointArr = vectorObj.coordinates;
    const styleObj = vectorObj.style || {};
    const textStyle = vectorObj.textStyle || {};
    const markerInfo = vectorObj.info;

    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new Point(pointArr)
    });
    //设置属性,用于加载弹窗
    if (markerInfo) {
        feature[markerInfo.name] = markerInfo.info;
        this.infoKey = markerInfo.name;
    }
    let pointStyle;
    if (styleObj.src) {
        pointStyle = new Style({
            image: new Icon({
                src: styleObj.src, // 图标图片路径
                offset: styleObj.offset || [0, 0], // 图标的偏移量，单位是像素
                scale: styleObj.scale || 1, // 图标的缩放比例
                rotation: styleObj.rotation || 0 // 图标的旋转角度，单位是弧度
            })
        });
    } else {
        pointStyle = new Style({
            image: new Circle({
                radius: styleObj.radius || 0, // 圆点半径
                fill: new Fill({
                    color: styleObj.fillColor || 'rgba(0, 217, 255, 0.5)' // 填充颜色
                }),
                stroke: new Stroke({
                    color: styleObj.strokeColor || '#000000', // 边框颜色
                    width: styleObj.strokeWidth || 0 // 边框宽度
                })
            }),
            text: new Text({
                font: `${textStyle.fontSize || 0}px Calibri,sans-serif`, // 字体
                fill: new Fill({
                    color: textStyle.fillColor || '#000000' // 文本填充颜色
                }),
                stroke: new Stroke({
                    color: textStyle.strokeColor || '#ffffff', // 文本边框颜色
                    width: textStyle.strokeWidth || 2
                }),
                text: textStyle.text || '示例', // 文本内容
                offsetX: textStyle.offsetX || 0, // 水平偏移
                offsetY: textStyle.offsetY || 0, // 垂直偏移
                textAlign: textStyle.textAlign || 'center', // 文本对齐方式
                textBaseline: textStyle.textBaseline || 'middle' // 文本基线
            })
        });
    }

    // 设置矢量点样式
    feature.setStyle(pointStyle);
    return feature;
};

Vector.prototype.collisionStyle = function (feature, styleObj) {
    let count = feature.get('features').length;
    if (this.infoKey && feature.get('features')[0][this.infoKey]) {
        feature[this.infoKey] = feature.get('features')[0][this.infoKey];
    }
    if (count > 1) {
        // 获取第一个子要素的样式
        const firstFeatureStyle = feature.get('features')[0].getStyle();
        // 克隆原始样式并应用新文本
        const clonedStyle = firstFeatureStyle.clone();
        return clonedStyle;
    } else {
        // 非聚合点
        // console.log(feature.get('features')[0]);
        return feature.get('features')[0].getStyle();
    }
};

Vector.prototype.clearCollisionPoints = function (collisionLayer) {
    if (collisionLayer) {
        collisionLayer.getSource().clear();
        this.map.removeLayer(collisionLayer);
        collisionLayer = null;
    }
};

/**
 * description 添加聚合点
 * @param points 点数值，每个对象包含点坐标、相关信息
 */
Vector.prototype.addClusterPoints = function (vectorObj = {}) {
    let features = vectorObj.features;
    let distance = vectorObj.distance;
    let styleObj = vectorObj.style || {};

    if (this.clusterLayer) {
        this.clusterLayer.getSource().clear();
    }

    let vectorSource = new VectorSource();
    features.forEach((feature) => {
        vectorSource.addFeature(feature);
    });

    let clusterPondSource = new Cluster({
        distance: distance || 100,
        source: vectorSource
    });

    let self = this;
    this.clusterLayer = new VectorLayer({
        id: 'layerPondIcon',
        title: 'layerPondIcon',
        source: clusterPondSource,
        zIndex: 30,
        style: function (feature) {
            return self.clusterStyle(feature, styleObj);
        }
    });

    this.map.addLayer(this.clusterLayer);
    return this.clusterLayer;
};

/**
 * @description: 设置单个聚合点样式
 * @param {*} vectorObj
 * pointArr 坐标,必传 格式[x,y]
 * layer 图层对象,必传
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}
 */
Vector.prototype.setClusterPoint = function (vectorObj) {
    const pointArr = vectorObj.coordinates;
    const styleObj = vectorObj.style || {};
    const markerInfo = vectorObj.info;

    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new Point(pointArr)
    });
    //设置属性,用于加载弹窗
    if (markerInfo) {
        feature[markerInfo.name] = markerInfo.info;
        this.infoKey = markerInfo.name;
    }
    let pointStyle;
    if (styleObj.src) {
        pointStyle = new Style({
            image: new Icon({
                src: styleObj.src, // 图标图片路径
                offset: styleObj.offset || [0, 0], // 图标的偏移量，单位是像素
                scale: styleObj.scale || 1, // 图标的缩放比例
                rotation: styleObj.rotation || 0 // 图标的旋转角度，单位是弧度
            })
        });
    } else {
        pointStyle = new Style({
            text: new Text({
                font: styleObj.font || '14px Calibri,sans-serif', // 字体
                fill: new Fill({
                    color: styleObj.fillColor || '#000000' // 文本填充颜色
                }),
                stroke: new Stroke({
                    color: styleObj.strokeColor || '#ffffff', // 文本边框颜色
                    width: styleObj.strokeWidth || 2
                }),
                text: styleObj.text || '示例', // 文本内容
                offsetX: styleObj.offsetX || 0, // 水平偏移
                offsetY: styleObj.offsetY || 0, // 垂直偏移
                padding: styleObj.padding || [1, 5, 1, 5],
                backgroundFill: new Fill({
                    color: styleObj.backgroundFill || '#ffffff'
                }),
                backgroundStroke: new Stroke({
                    color: styleObj.backgroundStroke || '#000000',
                    width: styleObj.backgroundStrokeWidth || 1
                }),
                textAlign: styleObj.textAlign || 'center', // 文本对齐方式
                textBaseline: styleObj.textBaseline || 'middle' // 文本基线
            })
        });
    }

    // 设置矢量点样式
    feature.setStyle(pointStyle);
    return feature;
};

Vector.prototype.clusterStyle = function (feature, styleObj) {
    let count = feature.get('features').length;
    if (count > 1) {
        //聚合样式
        feature.isCluster = true; //用于根据属性添加点击事件
        return new Style({
            image: new Circle({
                // 圆形
                radius: styleObj.radius || 15, // 半径
                stroke: new Stroke({
                    // 边框
                    color: styleObj.strokeColor || '#fff',
                    width: styleObj.strokeWidth || 1 // 边框宽度
                }),
                fill: new Fill({
                    // 填充
                    color: styleObj.fillColor || '#b31c4e'
                })
            }),
            text: new Text({
                fill: new Fill({
                    //文本填充样式（即文字颜色)
                    color: styleObj.textFillColor || '#ffffff'
                }),
                font: styleObj.font || 'bold 14px sans-serif',
                text: count > 1 ? count.toString() : feature.get('features')[0].values_.name
            })
        });
    } else {
        // 非聚合点
        if (this.infoKey && feature.get('features')[0][this.infoKey]) {
            feature[this.infoKey] = feature.get('features')[0][this.infoKey];
        }
        // console.log(feature.get('features')[0]);
        return feature.get('features')[0].getStyle();
    }
};

Vector.prototype.clearClusterPoints = function () {
    if (this.clusterLayer) {
        this.clusterLayer.getSource().clear();
        this.map.removeLayer(this.clusterLayer);
        this.clusterLayer = null;
    }
};

/**
 * @description: 添加marker点和文本(单个)
 * @param {*} vectorObj
 * pointArr 坐标,必传 格式[x,y]
 * layer 图层对象,必传
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}
 */
Vector.prototype.addPointWithText = function (vectorObj) {
    const pointArr = vectorObj.coordinates;
    const pointStyleObj = vectorObj.pointStyle || {};
    const textStyleObj = vectorObj.textStyle || {};
    const markerInfo = vectorObj.info;

    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new Point(pointArr)
    });
    //设置属性,用于加载弹窗
    if (markerInfo) {
        feature[markerInfo.name] = markerInfo.info;
    }

    const pointStyle = new Style({
        image: new Circle({
            radius: pointStyleObj.radius || 18, // 圆点半径
            fill: new Fill({
                color: pointStyleObj.fillColor || '#b31c4e' // 填充颜色
            }),
            stroke: new Stroke({
                color: pointStyleObj.strokeColor || '#ffffff', // 边框颜色
                width: pointStyleObj.strokeWidth || 1 // 边框宽度
            })
        }),
        text: new Text({
            font: textStyleObj.font || '14px Calibri,sans-serif', // 字体
            fill: new Fill({
                color: textStyleObj.fillColor || '#ffffff' // 文本填充颜色
            }),
            stroke: new Stroke({
                color: textStyleObj.strokeColor || '#000000', // 文本边框颜色
                width: textStyleObj.strokeWidth || 1
            }),
            text: textStyleObj.text || '示例', // 文本内容
            offsetX: textStyleObj.offsetX || 0, // 水平偏移
            offsetY: textStyleObj.offsetY || 0 // 垂直偏移
        })
    });
    // 设置矢量点样式
    feature.setStyle(pointStyle);
    vectorObj.layer.getSource().addFeature(feature);
};

/**
 * @description: 添加marker点(单个)
 * @param {*} vectorObj
 * pointArr 坐标,必传 格式[x,y]
 * layer 图层对象,必传
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}
 */
Vector.prototype.addPoint = function (vectorObj) {
    const pointArr = vectorObj.coordinates;
    const styleObj = vectorObj.style || {};
    const markerInfo = vectorObj.info;

    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new Point(pointArr)
    });
    //设置属性,用于加载弹窗
    if (markerInfo) {
        feature[markerInfo.name] = markerInfo.info;
    }

    const pointStyle = new Style({
        image: new Circle({
            radius: styleObj.radius || 15, // 圆点半径
            fill: new Fill({
                color: styleObj.fillColor || 'rgba(0, 217, 255, 0.5)' // 填充颜色
            }),
            stroke: new Stroke({
                color: styleObj.strokeColor || '#000000', // 边框颜色
                width: styleObj.strokeWidth || 0 // 边框宽度
            })
        })
    });
    // 设置矢量点样式
    feature.setStyle(pointStyle);
    vectorObj.layer.getSource().addFeature(feature);
};

/**
 * @description: 添加text点(单个)
 * @param {*} vectorObj
 * pointArr 坐标,必传 格式[x,y]
 * layer 图层对象,必传
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}
 */
Vector.prototype.addText = function (vectorObj) {
    const pointArr = vectorObj.coordinates;
    const styleObj = vectorObj.style || {};
    const markerInfo = vectorObj.info;

    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new Point(pointArr)
    });
    //设置属性,用于加载弹窗
    if (markerInfo) {
        feature[markerInfo.name] = markerInfo.info;
    }

    const pointStyle = new Style({
        text: new Text({
            font: styleObj.font || '14px Calibri,sans-serif', // 字体
            fill: new Fill({
                color: styleObj.fillColor || '#000000' // 文本填充颜色
            }),
            stroke: new Stroke({
                color: styleObj.strokeColor || '#ffffff', // 文本边框颜色
                width: styleObj.strokeWidth || 2
            }),
            text: styleObj.text || '示例', // 文本内容
            offsetX: styleObj.offsetX || 0, // 水平偏移
            offsetY: styleObj.offsetY || 0, // 垂直偏移
            textAlign: styleObj.textAlign || 'center', // 文本对齐方式
            textBaseline: styleObj.textBaseline || 'middle' // 文本基线
        })
    });
    // 设置矢量点样式
    feature.setStyle(pointStyle);
    vectorObj.layer.getSource().addFeature(feature);
};

/**
 * @description: 添加icon点(单个)
 * @param {*} vectorObj
 * pointArr 坐标,必传 格式[x,y]
 * layer 图层对象,必传
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}
 */
Vector.prototype.addIcon = function (vectorObj) {
    const pointArr = vectorObj.coordinates;
    const styleObj = vectorObj.style || {};
    const markerInfo = vectorObj.info;

    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new Point(pointArr)
    });
    //设置属性,用于加载弹窗
    if (markerInfo) {
        feature[markerInfo.name] = markerInfo.info;
    }

    const style = new Style({
        image: new Icon({
            src: styleObj.src, // 图标图片路径
            offset: styleObj.offset || [0, 0], // 图标的偏移量，单位是像素
            scale: styleObj.scale || 1, // 图标的缩放比例
            rotation: styleObj.rotation || 0 // 图标的旋转角度，单位是弧度
        })
    });
    // 设置矢量点样式
    feature.setStyle(style);
    vectorObj.layer.getSource().addFeature(feature);
};

/**
 * @description: 添加线(单条线)
 * @param {*} vectorObj
 * lineArr 坐标,必传 格式[[x,y],[x,y]]
 * layer 图层对象,必传
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}
 */
Vector.prototype.addLine = function (vectorObj) {
    const lineArr = vectorObj.coordinates;
    const styleObj = vectorObj.style || {};
    const markerInfo = vectorObj.info;

    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new LineString(lineArr)
    });
    //设置属性,用于加载弹窗
    if (markerInfo) {
        feature[markerInfo.name] = markerInfo.info;
    }

    const style = new Style({
        fill: new Fill({
            color: styleObj.fillColor || 'rgba(0, 217, 255, 0.5)' // 填充颜色（如果需要填充区域）
        }),
        stroke: new Stroke({
            color: styleObj.strokeColor || 'rgba(0, 0, 0, 1)', // 线的颜色
            width: styleObj.strokeWidth || 0 // 线的宽度
            // lineDash: [10, 10], // 虚线样式，数组表示虚线的绘制模式
            // lineCap: 'round', // 线的末端样式，可选值：'butt'、'round'、'square'
            // lineJoin: 'round' // 线的连接样式，可选值：'bevel'、'round'、'miter'
        })
    });
    // 设置矢量点样式
    feature.setStyle(style);
    vectorObj.layer.getSource().addFeature(feature);
};

/**
 * @description: 添加面(单个面)
 * @param {*} vectorObj
 * polygonArr 坐标,必传 格式 [[x1,y1],[x2,y2],[x3,y3],[x1,y1]]
 * layer 图层对象,必传
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}
 */
Vector.prototype.addPolygon = function (vectorObj) {
    const polygonArr = vectorObj.coordinates;
    const styleObj = vectorObj.style || {};
    const markerInfo = vectorObj.info;

    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new Polygon([polygonArr])
    });
    //设置属性,用于加载弹窗
    if (markerInfo) {
        feature[markerInfo.name] = markerInfo.info;
    }

    const style = new Style({
        stroke: new Stroke({
            color: styleObj.strokeColor || 'rgba(0, 0, 0, 1)', // 线的颜色
            width: styleObj.strokeWidth || 1 // 线的宽度
            // lineDash: [10, 10], // 虚线样式，数组表示虚线的绘制模式
            // lineCap: 'round', // 线的末端样式，可选值：'butt'、'round'、'square'
            // lineJoin: 'round' // 线的连接样式，可选值：'bevel'、'round'、'miter'
        }),
        fill: new Fill({
            color: styleObj.fillColor || 'rgba(0, 217, 255, 0.5)' // 填充颜色（如果需要填充区域）
        })
    });
    // 设置矢量点样式
    feature.setStyle(style);
    vectorObj.layer.getSource().addFeature(feature);
};

export default Vector;
